import {
    _decorator,
    Sprite,
    Node,
    SpriteFrame,
    Rect,
    Prefab,
    instantiate,
    Vec2,
    Vec3,
    UITransform,
    randomRangeInt,
    randomRange
} from 'cc';
import BaseView from '../../../../../../extensions/app/assets/base/BaseView';
import {IMiniViewNames} from '../../../../../app-builtin/app-admin/executor';
import {app} from "db://assets/app/app";
import {PopSetting} from "db://assets/app-bundle/app-view/pop/setting/native/PopSetting";
import {Draggable} from "db://assets/app-bundle/app-view/page/game/native/expansion/Draggable";
import {PopSuccess} from "db://assets/app-bundle/app-view/pop/success/native/PopSuccess";

const {ccclass, property} = _decorator;

// 麻将牌类型定义
export enum TileType {
    WAN = 1,    // 万
    TIAO = 2,   // 条
    TONG = 3,   // 筒
}

// 麻将牌定义
export interface MahjongTile {
    type: TileType;
    value: number;
    spriteFrame?: SpriteFrame;
}

@ccclass('PageGame')
export class PageGame extends BaseView {

    @property(Prefab)
    mahjongPrefab: Prefab = null; // 麻将牌 Prefab

    @property({
        tooltip: '生成的麻将牌数量'
    })
    mahjongCount: number = 20; // 默认生成 20 张麻将牌

    @property(Node)
    spawnAreaNode: Node = null; // 目标区域节点，用于确定生成范围

    @property(Node)
    autoSortAreas: Node[] = []  //可停放的区域

    private tileSprites: SpriteFrame[] = [];
    // 子界面列表，数组顺序为子界面排列顺序
    protected miniViews: IMiniViewNames = [];

    /**
     * 获取牌的精灵图
     * @param tile 牌数据
     */
    private getTileSpriteFrame(tile: MahjongTile): SpriteFrame {
        const spriteName = `${tile.type}${tile.value}`;
        return this.tileSprites.find(sf => sf.name === spriteName);
    }

    /**
     * 加载游戏所需资源
     */
    private async loadResources(): Promise<void> {
        try {
            const [tileSprites] = await Promise.all([
                this.loadSpriteFrames('main/大尺寸牌面'),
            ]);

            this.tileSprites = tileSprites;
        } catch (error) {
            console.error('资源加载失败:', error);
        }
    }

    /**
     * 加载精灵图集
     * @param path 资源路径
     */
    private loadSpriteFrames(path: string): Promise<SpriteFrame[]> {
        return new Promise((resolve, reject) => {
            app.manager.loader.loadDir({
                type: SpriteFrame,
                bundle: 'page-game-res',
                path: path,
                onComplete: (spriteFrames: SpriteFrame[] | null) => {
                    spriteFrames ? resolve(spriteFrames) : reject(new Error(`加载路径 ${path} 失败`));
                },
            });
        });
    }

    private generateMahjongTile(): MahjongTile[] {
        let res: MahjongTile[] = []
        let cnt = Math.ceil(this.mahjongCount / 3);
        for (let i = 0; i < cnt; i++) {
            let newTile: MahjongTile = {
                type: randomRangeInt(1, 3),
                value: randomRangeInt(1, 9)
            }
            res.push(newTile)
            res.push(newTile)
            res.push(newTile)
        }
        return res
    }

    /**
     * 在指定区域内随机生成多个麻将牌
     */
    private generateRandomMahjongTiles(): void {
        if (!this.mahjongPrefab) {
            console.warn('mahjongPrefab 未设置，无法生成麻将牌！');
            return;
        }

        if (!this.spawnAreaNode) {
            console.warn('spawnAreaNode 未设置，无法确定生成区域！');
            return;
        }

        const parent = this.node.getChildByName('origin'); // 默认在当前节点下生成，也可以改为其他子节点

        // 获取目标区域节点的 UITransform 组件
        const uiTransform = this.spawnAreaNode.getComponent(UITransform);
        if (!uiTransform) {
            console.warn('spawnAreaNode 缺少 UITransform 组件，无法计算生成区域！');
            return;
        }

        // 计算生成区域的边界（假设区域以节点中心为基准）
        const areaWidth = uiTransform.width;
        const areaHeight = uiTransform.height;
        const areaX = this.spawnAreaNode.position.x - areaWidth / 2; // 左边界
        const areaY = this.spawnAreaNode.position.y - areaHeight / 2; // 下边界

        const spawnRect = new Rect(areaX, areaY, areaWidth, areaHeight);

        let mahjongTiles = this.generateMahjongTile();
        for (let i = 0; i < mahjongTiles.length; i++) {
            let newTile = mahjongTiles[i]
            // 1. 实例化麻将牌
            const mahjongNode = instantiate(this.mahjongPrefab);

            let sprite = mahjongNode.getChildByName('tile').getComponent(Sprite);
            sprite.spriteFrame = this.getTileSpriteFrame(newTile)
            mahjongNode.name = sprite.spriteFrame.name

            parent.addChild(mahjongNode);

            // 2. 设置随机位置（在 spawnRect 范围内）
            const randomX = randomRange(spawnRect.x, spawnRect.x + spawnRect.width);
            const randomY = randomRange(spawnRect.y, spawnRect.y + spawnRect.height);
            mahjongNode.setPosition(randomX, randomY);
            // 3.
            let draggableComponent = mahjongNode.getComponent(Draggable);
            draggableComponent.onChangeTargetArea = () => {
                this.autoSortAreas.forEach((area: Node, index) => {
                    const worldBounds = this.getNodeAreaWorldBounds(area)
                    if (this.isPointInRect(mahjongNode.getWorldPosition(), worldBounds)) {
                        this.setDraggableTargetArea(mahjongNode, area)
                    }
                })

            }

        }
    }

    /**
     * 动态设置某个节点上的 Draggable 组件的 targetArea
     * @param draggableNode 挂载了 Draggable 组件的节点
     * @param newTargetArea 新的目标区域节点
     */
    public setDraggableTargetArea(draggableNode: Node, newTargetArea: Node): void {
        if (!draggableNode || !newTargetArea) {
            console.warn('setDraggableTargetArea: 参数无效，draggableNode 或 newTargetArea 为空！');
            return;
        }

        // 获取 draggableNode 上的 Draggable 组件
        const draggableComponent = draggableNode.getComponent(Draggable);
        if (!draggableComponent) {
            console.warn(`setDraggableTargetArea: 节点 ${draggableNode.name} 上未找到 Draggable 组件！`);
            return;
        }
        // 设置新的 targetArea
        draggableComponent.targetArea = newTargetArea;
    }

    /**
     * 获取节点包围盒（世界坐标系）
     */
    private getNodeAreaWorldBounds(area: Node): Rect {
        if (!area) return new Rect();

        const uiTransform = area.getComponent(UITransform);
        if (!uiTransform) {
            console.warn('目标区域节点缺少 UITransform 组件');
            return new Rect();
        }

        // 获取目标区域在本地坐标系下的包围盒
        const localRect = new Rect(0, 0, uiTransform.width, uiTransform.height);

        // 将本地包围盒转换为世界坐标系下的包围盒
        const worldPos = area.getWorldPosition();
        const anchorX = uiTransform.anchorX; // 锚点 x（0~1）
        const anchorY = uiTransform.anchorY; // 锚点 y（0~1）

        // 计算世界坐标系下的包围盒
        const left = worldPos.x - uiTransform.width * anchorX;
        const right = left + uiTransform.width;
        const bottom = worldPos.y - uiTransform.height * anchorY;
        const top = bottom + uiTransform.height;

        return new Rect(left, bottom, right - left, top - bottom);
    }

    /**
     * 判断一个点是否在矩形区域内
     */
    private isPointInRect(point: Vec3, rect: Rect): boolean {
        return (
            point.x >= rect.x &&
            point.x <= rect.x + rect.width &&
            point.y >= rect.y &&
            point.y <= rect.y + rect.height
        );
    }

    // ==================== 周期函数 ====================
    // 初始化的相关逻辑写在这
    onLoad() {
    }

    // 界面打开时的相关逻辑写在这(onShow可被多次调用-它与onHide不成对)
    async onShow(params: any) {
        this.showMiniViews({views: this.miniViews});
        if (params) {
            console.log(params)
            this.mahjongCount = params.mahjongCount
        }
        await this.loadResources();
        // 在资源加载完成后，生成随机麻将牌
        this.generateRandomMahjongTiles();
        app.manager.sound.playMusic({name: 'music/misic', force: true, volume: 0.3})
        this.node.getChildByName('origin').on(Node.EventType.CHILD_REMOVED, this.onChildRemoved, this);
    }

    // 界面关闭时的相关逻辑写在这(已经关闭的界面不会触发onHide)
    onHide(result: undefined) {
        app.store.game.restart()
        return result;
    }

    // ==================== 脚本逻辑 ====================
    onChildRemoved(child: Node) {
        console.log(this.node.getChildByName('origin').children.length)
        if (this.node.getChildByName('origin').children.length === 0) {
            app.manager.ui.show<PopSuccess>({name: 'PopSuccess'})
        }
    }

    // ==================== 动作按钮逻辑 ====================
    onSetting() {
        app.manager.ui.show<PopSetting>({name: 'PopSetting'})
    }
}